package chen.web.user;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import chen.web.MyContextProvider;
import chen.web.cache.CacheUtils;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.util.NewBeanInstanceStrategy;

public class PermissionConfigRepository {

	private static Log log = LogFactory.getLog(PermissionConfigRepository.class);
	private static Cache PermissionConfigCache;
	
	static{
		CacheConfiguration config = new CacheConfiguration("PermissionConfigCache", Integer.MAX_VALUE)
										.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.FIFO)
										.eternal(false)
										.diskPersistent(false);
		PermissionConfigCache = new Cache(config);
		CacheManager.create().addCache(PermissionConfigCache);
		CacheUtils.storeDescription(PermissionConfigCache, "缓存角色的权限配置");
	}
	
	@SuppressWarnings("unchecked")
	public static <T extends PermissionConfig> T load(Role role, Class<T> clazz){
		String path = path(role, clazz);
		Element element = PermissionConfigCache.get(path);
		T config = null;
		if(element == null){
			config = _load(path, clazz);
			element = new Element(path, config);
			PermissionConfigCache.put(element);
		}else {
			config = (T) element.getObjectValue();
		}
		return config;
	}
	
	@SuppressWarnings("unchecked")
	private static <T extends PermissionConfig> T _load(String path, Class<T> clazz){
		StringBuffer sb = new StringBuffer();
		try {
			FileInputStream fis = new FileInputStream(path);
			InputStreamReader reader = new InputStreamReader(fis, "UTF-8");
			for(int i=reader.read(); i != -1; i=reader.read()){
				sb.append((char)i);
			}
			reader.close();
			fis.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException(e);
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException(e);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException(e);
		} 
		JsonConfig jc = new JsonConfig();
		//jc.setNewBeanInstanceStrategy(strategy);
		jc.setRootClass(clazz);
		JSONObject json = JSONObject.fromObject(sb.toString());
		T config =  (T) JSONObject.toBean(json, jc);
		return config;
	}
	
	public static void persist(Role role, PermissionConfig config){
		String path = path(role, config.getClass());
		String json = JSONObject.fromObject(config).toString();
		try {
			FileOutputStream fis = new FileOutputStream(path);
			OutputStreamWriter writer = new OutputStreamWriter(fis, "UTF-8");
			writer.write(json);
			writer.close();
			fis.close();
			if(log.isDebugEnabled()){
				log.debug("持久化角色权限配置, 位置:" + path);	
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException(e);
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException(e);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException(e);
		}

	}
	
	public static <T extends PermissionConfig> T loadCurrent(Class<T> clazz){
		return PermissionConfigRepository.load(MyContextProvider.getMyContext().getAccount().getRole(), clazz);
	}

	private static class MyNewBeanInstanceStrategy extends NewBeanInstanceStrategy{
		private Role role = null;
		public MyNewBeanInstanceStrategy(Role role){
			this.role = role;
		}
		@Override
		public Object newInstance(Class clazz, JSONObject arg1)
				throws InstantiationException, IllegalAccessException,
				SecurityException, NoSuchMethodException,
				InvocationTargetException {
			// TODO Auto-generated method stub
			return clazz.getDeclaredConstructor(Role.class).newInstance();
		}
		
	}
	
	private static String path(Role role, Class<?> clazz){
		StringBuffer sb = new StringBuffer();
		sb.append(PermissionConfigRepository.class.getResource("/chen/web/config/permission").getPath());
		sb.append(File.separator)
			.append(clazz.getSimpleName())
			.append("-")
			.append(role.getId())
			.append(".per");
		return sb.toString();
	}
	
}
